/**
 * 控制配置
 */
import fs from 'fs';
import loader from '../kernel/tools/loader';
import path from 'path'
import sugar from '../kernel/tools/sugar';
import controRoute from '../kernel/route/controRoute';
import Middleware from '../kernel/middleware/middleware';
import Ioc from '../kernel/core/Ioc';
import Config from '../model/Config';


if(!global.cgem_config)
if(fs.existsSync(process.cwd()+"/cgem.config.json")){
    // 导入配置文件并且初始化
    global.cgem_config = init(require(process.cwd()+"/cgem.config.json"));
    // 初始化一下
}else{
    global.cgem_config = new Config();
}

// 初始化模块加载器
global.loader = loader.createLoader(global.cgem_config?.modules || {});
let config:config = global.cgem_config;

class controConfig {
    // 添加扩展 扩展必须是可直接使用的方法
    static addPlug(id:Function|any):void{
        global.cgem_config.plug.push(id.default || id)
    }
    // 获取扩展
    static getPlug():Array<controllerStructure>{
        return global.cgem_config.plug;
    }
    // 设置扩展
    static setPlug(data:Array<controllerStructure>){
        global.cgem_config.plug = data;
    }
    // 返回配置文件
    static getConfig():config{
        return config;
    }

    // 获取启动服务配置
    static getServers():{host:string,port:number};
    static getServers(id:string):{host:string,port:number}|string|number|Function;
    static getServers(id?:string):{host:string,port:number}|string|number|Function{
        if(id !== undefined) return config.server[id];
        return config.server;
    }
    
    // 获取特性信息
    static getFeatures():Record<string,boolean>;
    static getFeatures(id:string):boolean;
    static getFeatures(id?:string):any{
        if(id !== undefined) return config.features[id]
        return config.features;
    }

    // 获取全局模块
    static getModules():Record<string,string>{
        return config.modules;
    }

    // 获取中间件
    static getMiddleware(id:string):string;
    static getMiddleware():Record<string,string>;
    static getMiddleware(id?:string):Record<string,string>|string{
        if(id !== undefined) return config.middleware[id];
        return config.middleware;
    }

    // 获取全局中间件
    static getGlobal_Middleware():Array<string|Function>{
        return config.global_middleware;
    }

    // 获取注解配置
    static getAnnotation(id:string):string;
    static getAnnotation():Record<string,string>;
    static getAnnotation(id?:string):Record<string,string>|string{
        if(id !== undefined) return config.annotation[id];
        return config.annotation;
    }

    // 获取地址
    static getAddress(id?:string):string|Record<string,string>|any{
        if(id !== undefined) return config.address[id];
        return config.address;
    }

    // 获取运行注解的地址
    static getrunAnnotation():Array<string>{
        return config.runAnnotation;
    }

    // 获取路由文件的配置
    static getrouteConfig():Array<routeFile>;
    static getrouteConfig(id:string):routeFile;
    static getrouteConfig(id?:string):Array<routeFile>|routeFile{
        if(id !== undefined)
        return config.routeConfig[id]
        return config.routeConfig;
    }

    // 获取特殊接口的配置
    static getSpecial(id?:string):specialInter|Record<string,specialInter>{
        if(id !== undefined) return config.special[id];
        return config.special;
    }

    // 获取语法糖
    static getpathSugar(id:string) :string;
    static getpathSugar() :Record<string,string>;
    static getpathSugar(id?:string) :string|Record<string,string>{
        if(id !== undefined) return config.pathSugar[id];
        return config.pathSugar;
    }

    //===============================================================

    // 设置配置文件
    static setConfig(file:config):void{
        config = file;
    }

    // 设置启动服务配置
    static setServers(id:string|{host:string,port:number},v?:string|any):void{
        if(typeof id === 'object')
            config.server = id;
        else
            config.server[id] = v;
    }

    // 设置特性信息
    static setFeatures(id:string,v:string):void{
        config.features[id] = v;
    }

    // 添加全局模块
    static addModules(id:string,v:string):void{
        config.modules[id] = sugar.path(path.join(v),{superNumber:3});
    }

    // 添加中间件
    static addMiddleware(id:string,v:string|any):void{
        if(typeof v === 'function'){
            // 匿名方法直接加到 路由的中间件池中
            controRoute.addMiddleware(id,{
                module:{async run(...param:any[]){return await v(...param)}},
                methodName:"",
                parameter:[],
                isInterface:true
            })
        }else{
            // 是中间字符串 解析路径
            v = sugar.path(path.join(v),{superNumber:3});
            if(!/^[./\\]|^[A-Z]\:/.test(v)){
                if(!controConfig.getAddress("middleware")){throw new Error("please set middleware address")}
                config.middleware[id] = controConfig.getAddress("middleware") + "/" + v;
            }else{
                config.middleware[id] =  v;
            }
            // 添加到路由中间件池
            controRoute.addMiddleware(id,Middleware.pars_string_middleware(config.middleware[id],id,[]))
        }
    }

    // 添加全局中间件
    static addGlobal_Middleware(v:string|Function):void{
        if(typeof v === "string")
            config.global_middleware.push(v);
        else
            controRoute.addGlobalMiddleware(v);
    }

    // 添加注解配置
    static addAnnotation(id:string,v:string|any):void{
        if(typeof v === "string")v = path.join(v);
        config.annotation[id] = v;
    }

    // 添加地址
    static addAddress(id:string,v:string):void{
        config.address[id] = path.join(v);
    }

    // 添加运行注解的地址
    static addrunAnnotation(v:string):void{
        config.runAnnotation.push(path.join(v));
    }

    // 添加路由文件的配置
    static addrouteConfig(v:routeFile):void{
        v.path =path.join(v.path);
        config.routeConfig.push(v);
    }

    // 添加特殊接口的配置
    static addSpecial(id:string,v:specialInter):void{
        v.path = path.join(v.path);
        config.special[id] = v;
    }

    // 添加语法糖
    static addpathSugar(id:string,v:string):void{
        config.pathSugar[id] = v;
    }
}

if(module) module.exports = controConfig;
export default controConfig;

// 初始化导入的配置
function init(con:config):config{
    let config:config = new Config();
    Object.keys(config).forEach(e=>{
        con[e] || (con[e] = config[e])
    })
    return con;
}

//注入一些数据到配置中=======================================================================================

// 服务启动配置
controConfig.getServers("host") || controConfig.setServers("host","0.0.0.0");
controConfig.getServers("port") || controConfig.setServers("post","8088");

// 框架自带的自动装载的注解
// 挂载中间件
controConfig.addAnnotation("Middleware",path.join(__dirname,"../annotation/Middleware"));
// 挂载控制器
controConfig.addAnnotation("Controller",path.join(__dirname,"../annotation/Controller"));
// 挂载注解
controConfig.addAnnotation("Annotation",path.join(__dirname,"../annotation/Annotation"));

controConfig.addAnnotation("GetMapping",path.join(__dirname,"../annotation/GetMapping"));
controConfig.addAnnotation("PostMapping",path.join(__dirname,"../annotation/PostMapping"));
controConfig.addAnnotation("AnyMapping",path.join(__dirname,"../annotation/AnyMapping"));
controConfig.addAnnotation("route_midd",path.join(__dirname,"../annotation/route_midd"));
controConfig.addAnnotation("page_midd",path.join(__dirname,"../annotation/page_midd"));
controConfig.addAnnotation("get",path.join(__dirname,"../annotation/auto_load_route"));
controConfig.addAnnotation("post",path.join(__dirname,"../annotation/auto_load_route"));
controConfig.addAnnotation("any",path.join( __dirname,"../annotation/auto_load_route"));
controConfig.addAnnotation("midd",path.join(__dirname,"../annotation/auto_load_route"));
controConfig.addAnnotation("end_controller",path.join(__dirname,"../annotation/auto_load_route"));


// 中间件，控制器的地址(文件夹地址)
// 公共文件的地址
controConfig.getAddress("public") || controConfig.addAddress("public",process.cwd()+"/public");

// 负责special状态的控制 如404 500 public读取等
// 赋予默认值
controConfig.getSpecial("404") || controConfig.addSpecial("404",{path:path.join( __dirname,"../entrance/specialInterface/404"),middleware:[],parameter:[]});
controConfig.getSpecial("500") || controConfig.addSpecial("500",{path:path.join(__dirname,"../entrance/specialInterface/500"),middleware:[],parameter:[]});
controConfig.getSpecial("public") || controConfig.addSpecial("public",{path:path.join(__dirname,"../entrance/specialInterface/resourcesToRead"),middleware:[],parameter:[]})
// 解析接口
controConfig.getSpecial("requestParse") || controConfig.addSpecial("requestParse",{path:path.join(__dirname,"../entrance/specialInterface/requestParse"),middleware:[],parameter:[]})
// 记录请求
controConfig.getSpecial("requestRecord") || controConfig.addSpecial("requestRecord",{path:path.join(__dirname,"../entrance/specialInterface/requestRecord"),middleware:[],parameter:[]})


//添加语法糖 公共文件夹路径
controConfig.addpathSugar("<public>",process.cwd()+"/public");

// 初始化路由文件
for(let e of controConfig.getrouteConfig()){
    e.prefix || (e.prefix="")
    e.middleware || (e.middleware = [])
    if(!e.path){
        throw new Error("路由文件路径没有配置")
    }
}

// 初始化ioc (也就是modules)
let modules = controConfig.getModules();
for(let e in modules){
    modules[e] = sugar.path(modules[e],{pathSugar:controConfig.getpathSugar()})
    // 把模块解析出来存放到Ioc容器中
    Ioc.add(e,modules[e])
}

// 初始化中间件
let Middlware = controConfig.getMiddleware()
for(let e in Middlware){
    if(!/^[./\\]|^[A-Z]\:/.test(Middlware[e])){
        // 这不是绝对路径，完善路径
        Middlware[e] = path.join(controConfig.getAddress("middleware") + "/" + Middlware[e]);
    }
    // 把中间件解析出来存放到中间件池中
    controRoute.addMiddleware(e,Middleware.auto_pars(Middlware[e],e))
}

// 初始化注解  这里可有可无，提前初始化相当与提前缓存
let annotation = controConfig.getAnnotation();
for(let e in annotation){
    // 判断一下注解的地址
    if(typeof annotation[e] === "string" && !/^[./\\]|^[A-Z]\:/.test(annotation[e])){
        // 如果文件不存在说明是第三方模块
        if(fs.existsSync( controConfig.getAddress("annotation") + "/" + annotation[e])){
            annotation[e] = controConfig.getAddress("annotation") +"/"+ annotation[e];
        }
        Ioc.add(e,annotation[e])
    }
}